﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Community.CsharpSqlite.Entity;
using System.Diagnostics;
namespace Community.CsharpSqlite
{
    class ConfigHelper
    {

        /*
    ** This API allows applications to modify the global configuration of
    ** the SQLite library at run-time.
    **
    ** This routine should only be called when there are no outstanding
    ** database connections or memory allocations.  This routine is not
    ** threadsafe.  Failure to heed these warnings can lead to unpredictable
    ** behavior.
    */
        // Overloads for ap assignments
        public static int Sqlite3Config(int op, sqlite3_pcache_methods ap)
        {
            //  va_list ap;
            int rc = StatusCode.SQLITE_OK;
            switch (op)
            {
                case ConfigOption.SQLITE_CONFIG_PCACHE:
                    {
                        /* Specify an alternative malloc implementation */
                        Global.Config.pcache = ap;
                        //Global.Config.pcache = (sqlite3_pcache_methods)Custom.VaArg(ap, "sqlite3_pcache_methods");
                        break;
                    }
            }
            return rc;
        }

        public static int Sqlite3Config(int op, ref sqlite3_pcache_methods ap)
        {
            //  va_list ap;
            int rc = StatusCode.SQLITE_OK;
            switch (op)
            {
                case ConfigOption.SQLITE_CONFIG_GETPCACHE:
                    {
                        if (Global.Config.pcache.xInit == null)
                        {
                          Sqlite3.sqlite3PCacheSetDefault();
                        }
                        ap = Global.Config.pcache;
                        //Custom.VaArg(ap, sqlite3_pcache_methods*) = Global.Config.pcache;
                        break;
                    }
            }
            return rc;
        }

        public static int Sqlite3Config(int op, sqlite3_mem_methods ap)
        {
            //  va_list ap;
            int rc = StatusCode.SQLITE_OK;
            switch (op)
            {
                case ConfigOption.SQLITE_CONFIG_MALLOC:
                    {
                        /* Specify an alternative malloc implementation */
                        Global.Config.m = ap; // (sqlite3_mem_methods)Custom.VaArg( ap, "sqlite3_mem_methods" );
                        break;
                    }
            }
            return rc;
        }

        public static int Sqlite3Config(int op, ref sqlite3_mem_methods ap)
        {
            //  va_list ap;
            int rc = StatusCode.SQLITE_OK;
            switch (op)
            {
                case ConfigOption.SQLITE_CONFIG_GETMALLOC:
                    {
                        /* Retrieve the current malloc() implementation */
                        //if ( Global.Config.m.xMalloc == null ) MemPool.MemSetDefault();
                        ap = Global.Config.m; //Custom.VaArg(ap, sqlite3_mem_methods*) =  Global.Config.m;
                        break;
                    }
            }
            return rc;
        }

#if SQLITE_THREADSAFE // && SQLITE_THREADSAFE>0
public static int Sqlite3Config( int op,  sqlite3_mutex_methods ap )
{
//  va_list ap;
int rc = StatusCode.SQLITE_OK;
switch ( op )
{
case ConfigOption.SQLITE_CONFIG_MUTEX:
{
/* Specify an alternative mutex implementation */
Global.Config.mutex = ap;// (sqlite3_mutex_methods)Custom.VaArg( ap, "sqlite3_mutex_methods" );
break;
}
}
return rc;
}

static int Sqlite3Config( int op, ref sqlite3_mutex_methods ap )
{
//  va_list ap;
int rc = StatusCode.SQLITE_OK;
switch ( op )
{
case ConfigOption.SQLITE_CONFIG_GETMUTEX:
{
/* Retrieve the current mutex implementation */
ap =  Global.Config.mutex;// *Custom.VaArg(ap, sqlite3_mutex_methods*) =  Global.Config.mutex;
break;
}
}
return rc;
}
#endif

        public static int Sqlite3Config(int op, params object[] ap)
        {
            //  va_list ap;
            int rc = StatusCode.SQLITE_OK;

            /* Sqlite3Config() shall return StatusCode.SQLITE_MISUSE if it is invoked while
      ** the SQLite library is in use. */
            if (Global.Config.isInit != 0) return UnitTest.SQLITE_MISUSE_BKPT();

            Custom.VaStart(ap, null);
            switch (op)
            {
                /* Mutex configuration options are only available in a threadsafe
    ** compile.
    */
#if SQLITE_THREADSAFE
case ConfigOption.SQLITE_CONFIG_SINGLETHREAD:
{
/* Disable all mutexing */
Global.Config.bCoreMutex = false;
Global.Config.bFullMutex = false;
break;
}
case ConfigOption.SQLITE_CONFIG_MULTITHREAD:
{
/* Disable mutexing of database connections */
/* Enable mutexing of core data structures */
Global.Config.bCoreMutex = true;
Global.Config.bFullMutex = false;
break;
}
case ConfigOption.SQLITE_CONFIG_SERIALIZED:
{
/* Enable all mutexing */
Global.Config.bCoreMutex = true;
Global.Config.bFullMutex = true;
break;
}
case ConfigOption.SQLITE_CONFIG_MUTEX: {
/* Specify an alternative mutex implementation */
Global.Config.mutex = *Custom.VaArg(ap, sqlite3_mutex_methods*);
break;
}
case ConfigOption.SQLITE_CONFIG_GETMUTEX: {
/* Retrieve the current mutex implementation */
*Custom.VaArg(ap, sqlite3_mutex_methods*) = Global.Config.mutex;
break;
}
#endif
                case ConfigOption.SQLITE_CONFIG_MALLOC:
                    {
                        Debugger.Break(); // TODO --
                        /* Specify an alternative malloc implementation */
                        Global.Config.m = (sqlite3_mem_methods)Custom.VaArg(ap, "sqlite3_mem_methods");
                        break;
                    }
                case ConfigOption.SQLITE_CONFIG_GETMALLOC:
                    {
                        /* Retrieve the current malloc() implementation */
                        //if ( Global.Config.m.xMalloc == null ) MemPool.MemSetDefault();
                        //Debugger.Break(); // TODO --//Custom.VaArg(ap, sqlite3_mem_methods*) =  Global.Config.m;
                        break;
                    }
                case ConfigOption.SQLITE_CONFIG_MEMSTATUS:
                    {
                        /* Enable or disable the malloc status collection */
                        Global.Config.bMemstat = (int)Custom.VaArg(ap, "int") != 0;
                        break;
                    }
                case ConfigOption.SQLITE_CONFIG_SCRATCH:
                    {
                        /* Designate a buffer for scratch memory space */
                        Global.Config.pScratch = (byte[][])Custom.VaArg(ap, "byte[][]");
                        Global.Config.szScratch = (int)Custom.VaArg(ap, "int");
                        Global.Config.nScratch = (int)Custom.VaArg(ap, "int");
                        break;
                    }

                case ConfigOption.SQLITE_CONFIG_PAGECACHE:
                    {
                        /* Designate a buffer for page cache memory space */
                        Global.Config.pPage = (MemPage)Custom.VaArg(ap, "MemPage");
                        Global.Config.szPage = (int)Custom.VaArg(ap, "int");
                        Global.Config.nPage = (int)Custom.VaArg(ap, "int");
                        break;
                    }

                case ConfigOption.SQLITE_CONFIG_PCACHE:
                    {
                        /* Specify an alternative page cache implementation */
                        Debugger.Break();
                        // TODO --Global.Config.pcache = (sqlite3_pcache_methods)Custom.VaArg(ap, "sqlite3_pcache_methods");
                        break;
                    }

                case ConfigOption.SQLITE_CONFIG_GETPCACHE:
                    {
                        if (Global.Config.pcache.xInit == null)
                        {
                            Sqlite3.sqlite3PCacheSetDefault();
                        }
                        Debugger.Break(); // TODO -- *Custom.VaArg(ap, sqlite3_pcache_methods*) = Global.Config.pcache;
                        break;
                    }

#if SQLITE_ENABLE_MEMSYS3 || SQLITE_ENABLE_MEMSYS5
case ConfigOption.SQLITE_CONFIG_HEAP: {
/* Designate a buffer for heap memory space */
Global.Config.pHeap = Custom.VaArg(ap, void*);
Global.Config.nHeap = Custom.VaArg(ap, int);
Global.Config.mnReq = Custom.VaArg(ap, int);

if(  Global.Config.pHeap==0 ){
/* If the heap pointer is NULL, then restore the malloc implementation
** back to NULL pointers too.  This will cause the malloc to go
** back to its default implementation when sqlite3_initialize() is
** run.
*/
memset(& Global.Config.m, 0, sizeof( Global.Config.m));
}else{
/* The heap pointer is not NULL, then install one of the
** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
** ENABLE_MEMSYS5 is defined, return an error.
*/
#if SQLITE_ENABLE_MEMSYS3
Global.Config.m = *sqlite3MemGetMemsys3();
#endif
#if SQLITE_ENABLE_MEMSYS5
Global.Config.m = *sqlite3MemGetMemsys5();
#endif
}
break;
}
#endif

                case ConfigOption.SQLITE_CONFIG_LOOKASIDE:
                    {
                        Global.Config.szLookaside = (int)Custom.VaArg(ap, "int");
                        Global.Config.nLookaside = (int)Custom.VaArg(ap, "int");
                        break;
                    }

                /* Record a pointer to the logger funcction and its first argument.
** The default is NULL.  Logging is disabled if the function pointer is
** NULL.
*/
                case ConfigOption.SQLITE_CONFIG_LOG:
                    {
                        /* MSVC is picky about pulling func ptrs from va lists.
      ** http://support.microsoft.com/kb/47961
      ** Global.Config.xLog = Custom.VaArg(ap, void(*)(void*,int,const char*));
      */
                        //typedef void(*LOGFUNC_t)(void*,int,const char*);
                        Global.Config.xLog = (dxLog)Custom.VaArg(ap, "LOGFUNC_t");
                        Global.Config.pLogArg = Custom.VaArg(ap, "void*");
                        break;
                    }
                default:
                    {
                        rc = StatusCode.SQLITE_ERROR;
                        break;
                    }
            }
            Custom.VaEnd(ap);
            return rc;
        }

    }
}
